package com.ljc.cjgl.service;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;

import org.abyss.data.specifications.Rule;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.ljc.cjgl.entitiy.Marking;
import com.ljc.cjgl.entitiy.ScoringGrade;
import com.ljc.cjgl.entitiy.Stu;
import com.ljc.cjgl.entitiy.TbClass;
import com.ljc.cjgl.entitiy.TbTest;
import com.ljc.cjgl.entitiy.TestRegister;
import com.ljc.cjgl.form.TestRegisterForm;
import com.ljc.cjgl.repository.MarkingResitory;
import com.ljc.cjgl.repository.ScoringGradeRepository;
import com.ljc.cjgl.repository.StuRepository;
import com.ljc.cjgl.repository.TestRegisterResitory;
import com.ljc.cjgl.repository.TestRepository;

@Service
public class TestRegisterService {
	@Autowired
	private TestRegisterResitory testRegisterDAO;
	@Autowired
	private MarkingResitory markingDAO;
	@Autowired
	private ScoringGradeRepository scoringGradeDAO;
	@Autowired
	private StuRepository studentDAO;
	@Autowired
	private TestRepository testDAO;
	
	public TestRegister findById(Integer id) {
		Optional<TestRegister> optional = testRegisterDAO.findById(id);
		if(optional.isPresent()) {
			return optional.get();
		}
		return null;
	}
	
	public List<TestRegister> findAll(){
		return testRegisterDAO.findAll();
	}
	
	public Page<TestRegister> findAll(Specification<TestRegister> spec,Pageable pageable){
		return testRegisterDAO.findAll(spec, pageable);
	}

	public void save(TestRegisterForm form) {
		TestRegister model=new TestRegister();
		if(form.getId()!=null) {
			model=findById(form.getId());
		}
		if(form.getTestId()!=null) {
			model.setTest(new TbTest(form.getTestId()));
		}
		if(form.getStudentId()!=null) {
			model.setStudent(new Stu(form.getStudentId()));
		}
		if(form.getIsShow()!=null) {
			model.setIsShow(form.getIsShow());
		}
		
		BeanUtils.copyProperties(form, model,"id","test","student","isShow","grade");
		testRegisterDAO.save(model);
	}

	public synchronized boolean delete(List<TestRegister> testRegisters) {
		try {
			for (TestRegister model : testRegisters) {
				if(model.getId()!=null) {
					testRegisterDAO.deleteById(model.getId());
				}
			}
			return true;
		} catch (Exception e) {
			return false;
		}
	}

	public List<TbTest> findDistinctTest() {
		return testRegisterDAO.findDistinctTest();
	}

	public List<TbClass> findDistinctStudentTbClass() {
		return testRegisterDAO.findDistinctStudentTbClass();
	}
	
	@Transactional
	public void calculate(Integer classId, Integer testId) {
		TbTest test=testDAO.findById(testId).get();
		test.setStatus(2);
		testDAO.save(test);
		List<Marking> markings = markingDAO.findByTestId(testId); 
		List<Integer> teacherIds=new ArrayList<Integer>();
		for (Marking marking : markings) {
			teacherIds.add(marking.getTeacher().getId());
		}
		HashSet<Rule> rules=new HashSet<>();
		rules.add(Rule.property("student.tbClass.id").equal(classId));
		rules.add(Rule.property("scoring.test.id").equal(testId));
		rules.add(Rule.property("teacher.id").in(teacherIds).not());
		List<ScoringGrade> wxtrs=scoringGradeDAO.findAll(Rule.and(rules).toSpecification());//无效的评分记录
		scoringGradeDAO.deleteAll(wxtrs); //删除无效的评分记录
		
		//找出所有考试注册信息
		List<TestRegister> testRegisters=testRegisterDAO.findByStudentTbClassIdAndTestId(classId,testId);
		for (TestRegister tr : testRegisters) {
			Integer studentId=tr.getStudent().getId();
			float grade=0;
			Integer rate=100;
			List<Marking> masters=markingDAO.findByTestIdAndRateNotNull(testId);
			for (Marking marking : masters) {
				Integer g = scoringGradeDAO.findSumGradeByTeacherIdAndStudentId(marking.getTeacher().getId(),studentId,testId);
				float g1=g==null?0:g;
				rate-=marking.getRate();
				g1=g1*marking.getRate()/100;
				grade+=g1;
			}
			float grade2=0;
			List<Marking> others=markingDAO.findByTestIdAndRateIsNull(testId);
			for (Marking marking : others) {
				Integer g1=scoringGradeDAO.findSumGradeByTeacherIdAndStudentId(marking.getTeacher().getId(),studentId,testId);
					grade2+=g1==null?0:g1;
			}
			grade+=grade2/others.size()*rate/100;
			tr.setGrade(Math.round(grade));
			testRegisterDAO.save(tr);
		}
	}

	public void gradeChange(Integer id, Integer grade) {
		TestRegister model=findById(id);
		model.setGrade(grade);
		testRegisterDAO.save(model);
	}

	public List<String> getTestXq() {
		return testRegisterDAO.getTestXq();
	}

	public List<String> getths(Integer classId, String xq) {
		List<String> btStrs=new ArrayList<>();
		btStrs.add("学号");
		btStrs.add("姓名");
		List<TbTest> testNames=testRegisterDAO.findTestNameByClassIdAndXq(classId,xq);
		for (TbTest test : testNames) {
			btStrs.add(test.getName());
		}
		return btStrs;
	}

	public List<List<Object>> getGradsBy(Integer classId, String xq) {
		List<List<Object>> grades=new ArrayList<>();
		List<Stu> students=studentDAO.findByTbClassId(classId);
		for (Stu student : students) {
			List<Object> row=new ArrayList<>();
			row.add(student.getStuNum());
			row.add(student.getName());
			List<TbTest> tests=testRegisterDAO.findTestNameByClassIdAndXq(classId,xq);
			for(TbTest test:tests) {
				TestRegister tr=this.findByStudentIdAndTestId(student.getId(),test.getId());
				row.add(tr==null?null:tr.getGrade());
			}
			grades.add(row);
		}
		return grades;
	}

	private TestRegister findByStudentIdAndTestId(Integer id, Integer id2) {
		Optional<TestRegister> optional=testRegisterDAO.findByStudentIdAndTestId(id,id2);
		if(optional.isPresent()) {
			return optional.get();
		}
		return null;
	}

	public TestRegister findByStudentId(Integer id) {
		List<TestRegister> list=testRegisterDAO.findByStudentId(id);
		if(list.isEmpty()) {
			return null;
		}
		return list.get(0);
	}

	public Page<TestRegister> findAll(PageRequest pageRequest) {
		return testRegisterDAO.findAll(pageRequest);
	}

	public Page<TestRegister> getPageByIsShow(boolean b, Pageable pageRequest) {
		return testRegisterDAO.findByIsShow(b,pageRequest);
	}

	public List<TestRegister> findByStudentTbClassId(Integer id) {
		return testRegisterDAO.findByStudentTbClassId(id);
	}

	public List<TbClass> findTbClassByTestId(Integer testId) {
		return testRegisterDAO.findTbClassByTestId(testId);
	}

	public List<Stu> findStuByTestId(Integer testId) {
		return testRegisterDAO.findStuByTestId(testId);
	}

	public List<Stu> findDistinctStu() {
		return testRegisterDAO.findDistinctStu();
	}
	
}
